<?php
//=======================================
//###################################
// Kayako Web Solutions
//
// Source Copyright 2001-2004 Kayako Web Solutions
// Unauthorized reproduction is not allowed
// License Number: $%LICENSE%$
// $Author: vshoor $ ($Date: 2006/04/11 20:58:15 $)
// $RCSfile: functions_attachments.php,v $ : $Revision: 1.13 $ 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###################################
//=======================================


if (!defined("INSWIFT")) {
	trigger_error("Unable to process $PHP_SELF", E_USER_ERROR);
}

require_once ("./includes/data_mimelist.php");

/**
* Attachment management class
*/
class TicketAttachments
{
	var $chunksize = 2097152; // 2 MB
	var $attachmenttype;
	var $storeprefix = "attach_";
	var $tempprefix = "temp_";


	/**
	* Constructor
	*/
	function TicketAttachments()
	{
		global $_SWIFT;

		$this->chunksize = $_SWIFT["settings"]["tickets_attachchunksize"];
		if ($_SWIFT["settings"]["tickets_attachtype"] == ATTACHMENT_DB)
		{
			$this->attachmenttype = ATTACHMENT_DB;
		} else {
			$this->attachmenttype = ATTACHMENT_FILE;
		}
	}

	/**
	* Generates a random store filename
	*/
	function generateStoreFilename()
	{
		return $this->storeprefix.buildHash();
	}

	/**
	* Converts Attachment Data to Chunks
	*/
	function dataToChunks($ticketid, $ticketpostid, $filename, $filesize, $filetype, $data)
	{
		global $dbCore, $_SWIFT;

		$storefilename = $this->generateStoreFilename();

		$attachmentid = $this->insertAttachment($ticketid, $ticketpostid, 0, $filename, $filesize, $filetype, $this->attachmenttype, iif($this->attachmenttype==ATTACHMENT_FILE, $storefilename));

		// Is attachment type set to files?
		if ($this->attachmenttype == ATTACHMENT_FILE)
		{
			$fp = fopen("./files/".$storefilename, "wb");
			if ($fp)
			{
				fwrite($fp, $data);
				fclose($fp);
			}

			@chmod("./files/".$storefilename, 0666);
		} else {
			// We need to add chunks for this file
			$chunkoffset = $chunkprocessed = 0;

			$chunkcount = ceil($filesize/$this->chunksize);
			for ($ii=0; $ii<$chunkcount; $ii++)
			{
				$chunkdata = substr($data, $chunkoffset, $this->chunksize);
				
				$this->insertAttachmentChunk($attachmentid, $chunkdata);

				$chunkoffset += $this->chunksize;
				$chunkprocessed += $this->chunksize;
				unset($chunkdata);
			}
		}
	}

	/**
	* Converts a file to chunks
	*/
	function fileToChunks($ticketid, $ticketpostid, $filepath, $filename, $filetype)
	{
		if (!file_exists($filepath))
		{
			return false;
		}

		$storefilename = $this->generateStoreFilename();
		
		$attachmentid = $this->insertAttachment($ticketid, $ticketpostid, 0, $filename, filesize($filepath), $filetype, $this->attachmenttype, iif($this->attachmenttype==ATTACHMENT_FILE, $storefilename));

		if ($this->attachmenttype == ATTACHMENT_FILE)
		{
			copy($filepath, "./files/".$storefilename);

			@chmod("./files/".$storefilename, 0666);
		} else {
			// Add the chunks
			$fp = fopen($filepath, "rb");
			if (!$fp)
			{
				return false;
			}

			do {
				$chunkdata = fread($fp, $this->chunksize); 
				if (strlen($chunkdata) == 0)
				{ 
					break;
				}

				// Insert the chunk
				$this->insertAttachmentChunk($attachmentid, $chunkdata);
				unset($chunkdata);
			} while(true); 

			fclose ($fp);
		}
	}

	/**
	* Insert an attachment entry and return the attachmentid
	*/
	function insertAttachment($ticketid, $ticketpostid, $downloaditemid, $filename, $filesize, $filetype, $attachtype, $storefilename)
	{
		global $dbCore;

		$dbCore->query("INSERT INTO `". TABLE_PREFIX ."attachments` (`ticketid`, `ticketpostid`, `downloaditemid`, `filename`, `filesize`, `filetype`, `dateline`, `attachmenttype`, `storefilename`) VALUES ('". $dbCore->escape($ticketid) ."', '". $dbCore->escape($ticketpostid) ."', '". intval($downloaditemid) ."', '". $dbCore->escape($filename) ."', '". $dbCore->escape($filesize) ."', '". $dbCore->escape($filetype) ."', '". $dbCore->escape(DATENOW) ."', '". $dbCore->escape($attachtype) ."', '". $dbCore->escape($storefilename) ."');");
		$attachmentid = $dbCore->lastInsertId();

		return $attachmentid;
	}

	/**
	* Add an attachment entry linked to downloads
	*/
	function addDownloadsAttachment($ticketid, $ticketpostid, $downloaditemid, $filename, $filetype, $filesize)
	{
		$this->insertAttachment($ticketid, $ticketpostid, $downloaditemid, $filename, $filesize, $filetype, ATTACHMENT_DL, "");
	}

	/**
	* Insert an Attachment Chunk
	*/
	function insertAttachmentChunk($attachmentid, $chunkdata)
	{
		global $dbCore;

		$dbCore->query("INSERT INTO `". TABLE_PREFIX ."attachmentchunks` (`attachmentid`, `contents`) VALUES ('". $dbCore->escape($attachmentid) ."', '". $dbCore->escape($chunkdata) ."');");

		return true;
	}

	/**
	* Loads up the attachment and sends it to user browser
	*/
	function dispatchAttachment($attachmentid, $ticketid)
	{
		global $dbCore, $_SWIFT, $mimelist, $module;

		$_attachment = $dbCore->queryFetch("SELECT a.*, tp.ticketid FROM `". TABLE_PREFIX ."attachments` AS a LEFT JOIN `". TABLE_PREFIX ."ticketposts` AS tp ON (a.ticketpostid = tp.ticketpostid) WHERE a.attachmentid = '". $dbCore->escape($attachmentid) ."';");
		if (empty($_attachment["attachmentid"]) || $_attachment["ticketid"] != $ticketid)
		{
			return false;
		}

		if(isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT'])) {
			// IE Bug in download name workaround
			ini_set( 'zlib.output_compression','Off' );
		}

		// Get the file extension
		$extension = strtolower(getFileExtension($_attachment["filename"]));
		if (!empty($mimelist[$extension]))
		{
			header("Content-Type: " . $mimelist[$extension][0] . SWIFT_CRLF);
		} else {
			header("Content-Type: application/force-download");
		}

		if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE")){
			header("Content-Disposition: attachment; filename=\"". $_attachment["filename"] ."\"");
		} else{
			header("Content-Disposition: attachment; filename=\"". $_attachment["filename"] ."\"");
		}

		header("Content-Transfer-Encoding: binary");
//		header("Content-Length: ". filesize("./files/".$_attachment["storedfilename"]));

		// Is the attachment stored as a file?
		if ($_attachment["attachmenttype"] == ATTACHMENT_FILE)
		{
			// Yes, just read out the file
			$fp = fopen("./files/".$_attachment["storefilename"], "rb");
			if (!$fp)
			{
				return false;
			}

			while(!feof($fp)) {
				echo fread($fp, 8192);
				flush();
			}

			fclose($fp);
		} else if ($_attachment["attachmenttype"] == ATTACHMENT_DL && $module->isRegistered(MODULE_DOWNLOADS)) {
			$_download = $dbCore->queryFetch("SELECT * FROM `". TABLE_PREFIX ."downloaditems` WHERE `downloaditemid` = '". intval($_attachment["downloaditemid"]) ."';");
			if ($_download["downloaditemid"])
			{
				$fp = fopen("./files/".$_download["storedfilename"], "rb");
				if (!$fp)
				{
					return false;
				}

				while(!feof($fp)) {
					echo fread($fp, 8192);
					flush();
				}

				fclose($fp);
			}
		} else if ($_attachment["attachmenttype"] == ATTACHMENT_DB) {
			// Attachment type is set to database, read the chunks into a temporary file
			$tempfile = $this->tempprefix.buildHash();

			$fp = fopen("./files/".$tempfile, "wb");
			if (!$fp)
			{
				return false;
			}

			$writecontents = "";

			$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."attachmentchunks` WHERE `attachmentid` = '". $dbCore->escape($attachmentid) ."' ORDER BY `chunkid` ASC;");
			while ($dbCore->nextRecord())
			{
				@fflush($fp);
				fwrite($fp, $dbCore->Record["contents"]);
			}
			@fflush($fp);
			fclose($fp);
			unset($fp);

			// Now that we have a temporary file, we need to pump out the combined chunks to the user
			$fp = fopen("./files/".$tempfile, "rb");
			if (!$fp)
			{
				return false;
			}

			$_contents = "";
			while(!feof($fp)) {
				echo fread($fp, 8192);
				flush();
			}

			fclose($fp);

			// Nuke the temporary file as we dont need it anymore
			unlink("./files/".$tempfile);
		}

		return true;
	}

	/**
	* Loads up the attachment and returns it
	*/
	function returnAttachment($attachmentid, $ticketid)
	{
		global $dbCore, $_SWIFT, $mimelist, $module;

		$_attachment = $dbCore->queryFetch("SELECT a.*, tp.ticketid FROM `". TABLE_PREFIX ."attachments` AS a LEFT JOIN `". TABLE_PREFIX ."ticketposts` AS tp ON (a.ticketpostid = tp.ticketpostid) WHERE a.attachmentid = '". $dbCore->escape($attachmentid) ."';");
		if (empty($_attachment["attachmentid"]) || $_attachment["ticketid"] != $ticketid)
		{
			return false;
		}

		// Get the file extension
		$extension = getFileExtension($_attachment["filename"]);

		// Is the attachment stored as a file?
		if ($_attachment["attachmenttype"] == ATTACHMENT_FILE)
		{
			// Yes, just read out the file
			$fp = fopen("./files/".$_attachment["storefilename"], "rb");
			if (!$fp)
			{
				return false;
			}

			while(!feof($fp)) {
				$_returndata .= fread($fp, 8192);
			}

			fclose($fp);

			return $_returndata;
		} else if ($_attachment["attachmenttype"] == ATTACHMENT_DL && $module->isRegistered(MODULE_DOWNLOADS)) {
			$_download = $dbCore->queryFetch("SELECT * FROM `". TABLE_PREFIX ."downloaditems` WHERE `downloaditemid` = '". intval($_attachment["downloaditemid"]) ."';");
			if ($_download["downloaditemid"])
			{
				$fp = fopen("./files/".$_download["storedfilename"], "rb");
				if (!$fp)
				{
					return false;
				}

				while(!feof($fp)) {
					$_returndata .= fread($fp, 8192);
				}

				fclose($fp);

				return $_returndata;
			}
		} else if ($_attachment["attachmenttype"] == ATTACHMENT_DB) {
			// Attachment type is set to database, read the chunks into a temporary file
			$tempfile = $this->tempprefix.buildHash();

			$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."attachmentchunks` WHERE `attachmentid` = '". $dbCore->escape($attachmentid) ."' ORDER BY `chunkid` ASC;");
			while ($dbCore->nextRecord())
			{
				$_returndata .= $dbCore->Record["contents"];
			}

			return $_returndata;
		}

		return false;
	}

	/**
	* Returns the file extension from given filename
	*/
	function getFileExtension($filename)
	{
		$filearray = explode(".", $filename);
		$extension = $filearray[count($filearray)-1];
		
		if (empty($extension))
		{
			return false;
		} else {
			return $extension;
		}
	}
}
?>